/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
package org.apache.linkis.protocol.utils

import org.apache.linkis.common.ServiceInstance


object ZuulEntranceUtils {


  private val INSTANCE_SPLIT_TOKEN = "_"

  private val EXEC_ID = "exec_id"

  private val SPLIT_LEN = 3

  def parseExecID(longExecID: String): Array[String] = {
    //Add creator to execID while old code is compatible(添加creator到execID,同时老代码兼容)
    if (longExecID.startsWith(EXEC_ID)) {
      val content = longExecID.replaceFirst(EXEC_ID, "")
      val applicationNameLength = Integer.parseInt(content.substring(0, SPLIT_LEN))
      val instanceLength = Integer.parseInt(content.substring(SPLIT_LEN, SPLIT_LEN * 2))
      val applicationName = content.substring(SPLIT_LEN * 2, SPLIT_LEN * 2 + applicationNameLength)
      val instances = content.substring(SPLIT_LEN * 2 + applicationNameLength, SPLIT_LEN * 2 + applicationNameLength + instanceLength)
      val shortExecID = content.substring(SPLIT_LEN * 2 + applicationNameLength + instanceLength, content.length)
      Array[String](EXEC_ID, applicationName, instances, shortExecID)
    } else {
      // @Deprecated  将在之后删掉该部分内容
      val creatorLength = Integer.parseInt(longExecID.substring(0, 2))
      val executeLength = Integer.parseInt(longExecID.substring(2, 4))
      val instanceLength = Integer.parseInt(longExecID.substring(4, 6))
      val creator = longExecID.substring(6, 6 + creatorLength)
      val executeApplicationName = longExecID.substring(6 + creatorLength, 6 + creatorLength + executeLength)
      val instance = longExecID.substring(6 + creatorLength + executeLength, 6 + creatorLength + executeLength + instanceLength)
      val shortExecID = longExecID.substring(6 + creatorLength + executeLength + instanceLength, longExecID.length)
      Array(creator, executeApplicationName, instance, shortExecID)
    }
  }

  @Deprecated
  def generateExecID(shortExecID: String, executeApplicationName: String, instance: String, creator: String): String = {
    val creatorLength = getLengthStr(creator)
    val executeLength = getLengthStr(executeApplicationName)
    val instanceLength = getLengthStr(instance)
    creatorLength + executeLength + instanceLength + creator + executeApplicationName + instance + shortExecID
  }


  private def isNumberic(s: String): Boolean = {
    s.toCharArray foreach {
      c => if (c < 48 || c > 57) return false
    }
    true
  }

  /**
    *
    * @param shortExecID ExecID generated by the scheduler, such as IDE_hadoop_0(scheduler生成的ExecID, 如 IDE_hadoop_0)
    * @param executeApplicationName {dd}{dd}${executeApplicationName}${instance}${shortExecID}
    * @return
    */
  @Deprecated
  def generateExecID(shortExecID:String, executeApplicationName:String, instance:String):String = {
    val executeLength = getLengthStr(executeApplicationName)
    val instanceLength = getLengthStr(instance)
    if (shortExecID.split("_").length == 3) {
      //Backward compatible(向下兼容)
      val creator = shortExecID.split("_")(0)
      val creatorLength = getLengthStr(creator)
      return creatorLength + executeLength + instanceLength + creator + executeApplicationName + instance + shortExecID
    }
    executeLength + instanceLength + executeApplicationName + instance + shortExecID
  }

  def main(args: Array[String]): Unit = {
    val str = generateExecID("spark_test_01", "linkis-cg-entrance", Array[String]("127.0.0.1:8080"))
    val array = parseServiceInstanceByExecID(str)
    println(array(3))
  }

  def parseServiceInstanceByExecID(longExecID: String): Array[ServiceInstance] = {
    if (longExecID.startsWith(EXEC_ID)) {
      val content = longExecID.replaceFirst(EXEC_ID, "")
      val applicationNameLength = Integer.parseInt(content.substring(0, SPLIT_LEN))
      val instanceLength = Integer.parseInt(content.substring(SPLIT_LEN, SPLIT_LEN * 2))
      val applicationName = content.substring(SPLIT_LEN * 2, SPLIT_LEN * 2 + applicationNameLength)
      val instances = content.substring(SPLIT_LEN * 2 + applicationNameLength, SPLIT_LEN * 2 + applicationNameLength + instanceLength)
      val shortExecID = content.substring(SPLIT_LEN * 2 + applicationNameLength + instanceLength, content.length)
      instances.split(INSTANCE_SPLIT_TOKEN).map(ServiceInstance(applicationName, _))
    } else {
      // @Deprecated  将在之后删掉该部分内容
      val creatorLength = Integer.parseInt(longExecID.substring(0, 2))
      val executeLength = Integer.parseInt(longExecID.substring(2, 4))
      val instanceLength = Integer.parseInt(longExecID.substring(4, 6))
      val executeApplicationName = longExecID.substring(6 + creatorLength, 6 + creatorLength + executeLength)
      val instance = longExecID.substring(6 + creatorLength + executeLength, 6 + creatorLength + executeLength + instanceLength)
      Array(ServiceInstance(executeApplicationName, instance))
    }
  }


  private def getLengthStr(string: String): String = {
    val length = string.length
    if (length >= 10) String.valueOf(length) else "0" + String.valueOf(length)
  }

  def generateExecID(shortExecID: String, applicationName: String, instances: Array[String]): String = {
    if (null == instances || instances.isEmpty) {
      throw new RuntimeException("failed to generate ExecID ,the parameters instance is not null (生成ExecID失败，传入的Instance不能为空)")
    }
    val applicationNameLength = getStrFixedLen(applicationName, SPLIT_LEN)
    val instanceStr = instances.mkString(INSTANCE_SPLIT_TOKEN)
    val instanceStrLength = getStrFixedLen(instanceStr, SPLIT_LEN)
    EXEC_ID + applicationNameLength + instanceStrLength + applicationName + instanceStr + shortExecID
  }

  private def getStrFixedLen(string: String, len: Int): String = {
    val str = String.valueOf(string.length)
    val res = "0" * (len - str.length) + str
    res
  }

}
